#!/usr/bin/env python
# coding=utf-8
##from Src.tracker.spiders.auspost import types_track

import datetime,time
from vavava.util import LogAdapter,_interval_timer
from MySQLdb import OperationalError
from vavava.dbhelper import _db_conn_helper

class TrackStatus:
    def __init__(self,datalist=[]):
        self.shipment_iD     = datalist[0]
        self.track_type      = long(datalist[1])
        self.shipment_name   = datalist[2]
        self.shipment_status = datalist[3]
        self.create_time     = datalist[4]
        self.modify_time     = datalist[5]

class TrackData:
    """ Tracking summary """
    def __init__(self, track_type=-1, name="", track_time=datetime.datetime(2000,1,1), description="",
                 location="", shipment_id=-1, created=datetime.datetime(2000,1,1), id=-1 ):
        self.ID          = id
        self.track_type  = long(track_type)
        self.name        = name.strip()
        self.track_time  = track_time
        self.description = description.strip()
        self.location    = location.strip()
        self.shipment_id = shipment_id
        self.created     = created
        self.is_ended    = 0
        self.key         = None
        self._key_hash   = None
        self._init_key()

    def _init_key(self):
        self.key = "%s|%d|%s|%s|%s"%(
            self.name.strip(),
            self.track_type,
            self.track_time,
            self.description.strip(),
            self.location.strip()
            )
        self._key_hash = self.key.__hash__()

    @staticmethod
    def GetInstance(db_data):
        item = TrackData()
        item.id          = db_data[0]
        item.track_type  = long(db_data[1])
        item.name        = db_data[2].strip()
        item.track_time  = db_data[3]
        item.description = db_data[4].strip()
        item.location    = db_data[5].strip()
        item.shipment_id = db_data[6]
        item.created     = db_data[7]
        item._init_key()
        return item

    def __hash__(self):
        return self._key_hash

    def __eq__(self, other):
        """ define for dic key """
        result = self.key == other.key
        if result:
            pass
        else:
            pass
        return result

ITEM_RETRY_OUT = 10
class TrackDB(_db_conn_helper):
    def __init__(self,db_conn=None,log=None):
        _db_conn_helper.__init__(self,conn=db_conn,log=log)

    def __del__(self):
        if self._cursor:
            self._cursor.close()

#   def init_db_cursor(self,conn):
#        self._init_cursor(conn)

    def sp_insert_new_item(self, track_type, is_ended,name, track_time, description, location, retry_on_exception=True):
        """  insert a new track data  """
        try:
            self._conn.begin()
            track_time = track_time.strftime("%Y-%m-%d %H:%M:%S")
            result = self._cursor.callproc( "sp_insert_track_item",
                           [ track_type, str(is_ended).lower(), name, track_time, description, location ] )
            self._conn.commit()
            res = 0
            n = self._cursor.execute("select @result_")
            res = self._cursor.fetchone()
            if res:
                return res[0]
            else:
                return res
        except OperationalError as e:
            self._handle_exception(e)
            if retry_on_exception:
                self.sp_insert_new_item(track_type, is_ended,name, track_time, description, location, False)
        except Exception as e:
            self.log.exception(e)

    def sp_update_item_status(self,track_type, name, retry_timeout=True, retry_on_exception=True):
        """insert or update a track status"""
        try:
            self._conn.begin()
            flag = 0
            if retry_timeout:
                flag = 1
            result = self._cursor.callproc( "sp_update_track_item_status", [ track_type, name, flag ] )
            self._conn.commit()
            res = 0
            n = self._cursor.execute("select @timeout_count_")
            res = self._cursor.fetchone()
            return res
        except OperationalError as e:
            self._handle_exception(e)
            if retry_on_exception:
                self.sp_update_item_status(track_type, name, retry_timeout, False)
        except Exception as e:
            self.log.exception(e)

    def get_tracking_items(self, track_type):
        return self._get_item_list_by_sql(
            r'select * from track_status where tracktype_id=%d and shipment_status >= 0 and shipment_status < %d'
            % (track_type,ITEM_RETRY_OUT)
        )

    def get_delivered_items(self, track_type):
        return self._get_item_list_by_sql(
            r'select * from track_status where tracktype_id=%d and shipment_status = -1' % track_type
        )

    def get_timeout_items(self, track_type):
        return self._get_item_list_by_sql(
            r'select * from track_status where tracktype_id=%d and shipment_status = -2 or shipment_status >= %d'
            % (track_type,ITEM_RETRY_OUT)
        )

    def item_get_top_n(self, item, size, track_type, retry_on_exception=True):
        re_dict={}
        try:
            bt=_interval_timer()
            sql = r"select * from track_data where tracktype_id=%d and name = '%s' order by tracktime desc limit %d"\
                  % (track_type,item,size)
            n = self._cursor.execute(sql)
            for i in range(n):
                db_data = self._cursor.fetchone()
                db_item = TrackData.GetInstance(db_data)
                re_dict[db_item] = db_item #???
            interval = _interval_timer()-bt
            self.log.debug("interval:item_get_top_n(%s,%d) %f" % (item,len(re_dict),interval) )
        except OperationalError as e:
            self._handle_exception(e)
            if retry_on_exception:
                self.item_get_top_n(item,size,track_type,False)
        except Exception as e:
            self.log.exception(e)
        finally:
            return re_dict

    def _get_item_list_by_sql(self,sql, retry_on_exception=True):
        try:
            bt=_interval_timer()
            n = self._cursor.execute(sql)
            res = self._cursor.fetchall()
            res_dict = {}
            for each in res:
                if len(each) > 2:
                    ts = TrackStatus(each)
                    res_dict[ts.shipment_name] = ts
                else:
                    self.log.error( "result:%d" % len(each) )
            interval = _interval_timer()-bt
            self.log.debug("interval:_get_item_list_by_sql %f" % interval)
            return res_dict
        except OperationalError as e:
            self._handle_exception(e)
            if retry_on_exception:
                self._get_item_list_by_sql(sql,False)
        except Exception as e:
            self.log.exception(e)
        finally:
            pass

    def sp_log(self,msg,remark="", retry_on_exception=True):
        try:
            result = self._cursor.callproc( "_log", [ msg,remark ] )
        except OperationalError as e:
            self._handle_exception(e)
        except Exception as e:
            self.log.exception(e)
            if retry_on_exception:
                self.sp_log(msg,remark,False)
        finally:
            pass

    def sp_init_test_data(self, retry_on_exception=True):
        try:
            result = self._cursor.callproc( "sp_init_test_data", [ ] )
        except OperationalError as e:
            self._handle_exception(e)
            if retry_on_exception:
                self.sp_log(False)
        except Exception as e:
            self.log.exception(e)
        finally:
            pass












